from tkinter import *
from tkinter import ttk, font, filedialog as fd
import shutil, os, ctypes, pyglet
from fractions import Fraction
from PIL import ImageTk, Image, ImageOps, ImageDraw, ImageFont
import Program
import Edit_and_add_recipes
import Recipes_frame
from Ingredient import Ingredient
import Side_frame

class Edit_and_add_ingredients(Frame):
    """
    Purpose:
        Frame to edit and create new ingredients
    Instance variables:
        self.top_frame: frame containing search ingredients combo box
        self.ingredients_combo_box: combo box to search ingredients
        self.cost_frame: frame containing objects to change and view cost of ingredient
        self.cost_label: label displaying "Cost of Ingredient: $"
        self.cost_box: entry bo to change ingredient price
        self.unit_frame: frame containing ingredient unit information
        self.unit_label: displays "Per: "
        self.unit_combo_box: combo box to select the unit the ingredient uses, either
            "Oz" or "Unit"
        self.button_frame: frame containing buttons to remove, edit, or
            create ingredient
        self.add_button: creates a new ingredient with the provided name
        self.remove_ingredient_button: opens frame to delete the ingredient
        self.edit_button: button that edits the ingredient with the new price
        self.current_text: current text entered in the ingredient combo box
        self.last_text_is_current_ingredient: bool on if the text in the
            ingredient combo box is an ingredient
        self.done_button: closes frame
    Methods:
        ingredients_combo_box_clicked_event: toggles the bool on if the ingredient
            combo box was clicked
        update_combo_box_ingredients: updates the values in the ingredient combo box
        current_ingredient: updates the frame to display a current ingredient
        new_ingredient: updates frmae to display a new ingredient
        edit_clicked: handles changing price of ingredient when edit ingredient
            button is clicked
        add_clicked: handles creating a new ingredient when add button is clicked
        remove_clicked: opens window confirming you want to delete an ingredient
        delete_ingredient_process: process of deleting an ingredient from the program
    """

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.primary_color = "SystemButtonFace"
        self.primary_color_text = "black"
        self.bg_color = "SystemButtonFace"
        self.top_frame = Frame(self)
        self.top_frame.pack()
        self.ingredients_combo_box = ttk.Combobox(self.top_frame, height=5)
        self.ingredients_combo_box_clicked = False
        self.ingredients_combo_box.bind(
            "<KeyRelease>", lambda event: self.update_combo_box_ingredients()
        )
        self.ingredients_combo_box.bind(
            "<Button-1>",
            lambda _: (
                (
                    Program.Program.controller.default_combo_value_clear(
                        self.ingredients_combo_box, "Ingredient Name"
                    ),
                    self.ingredients_combo_box_clicked_event(),
                ),
            )
            if not self.ingredients_combo_box_clicked
            else None,
        )
        self.ingredients_combo_box.bind(
            "<<ComboboxSelected>>", lambda event: self.update_combo_box_ingredients()
        )
        self.ingredients_combo_box.grid()

        self.cost_frame = Frame(self)
        self.cost_frame.pack()
        self.cost_label = Label(self.cost_frame)
        self.cost_label.grid(row=0, column=0)
        self.cost_box = Entry(self.cost_frame, width=6)
        self.cost_box.bind(
            "<KeyPress>",
            lambda event: Program.Program.only_allow_num_and_equations(event),
        )
        self.cost_box.grid(row=0, column=1)

        self.unit_frame = Frame(self)
        self.unit_frame.pack()
        self.unit_label = Label(self.unit_frame, text="Per: ")
        self.unit_label.grid(row=0, column=0)
        self.unit_combo_box = ttk.Combobox(
            self.unit_frame, state="readonly", values=("Unit", "Oz"), width=4
        )
        self.unit_combo_box.current(0)
        self.unit_combo_box.grid(row=0, column=1)

        self.button_frame = Frame(self)
        self.button_frame.pack()
        self.add_button = Button(
            self.button_frame,
            text="Add Ingredient",
            command=lambda: self.add_clicked(),
        )
        self.add_button.grid(row=0, column=0, padx=5)
        self.remove_ingredient_button = Button(
            self.button_frame,
            text="Remove Ingredient",
            command=lambda: self.remove_clicked(parent),
        )
        self.remove_ingredient_button.grid(row=0, column=0, padx=5)
        self.edit_button = Button(
            self.button_frame,
            text="Edit Ingredient",
            command=lambda: self.edit_clicked(),
        )
        self.edit_button.grid(row=0, column=1, padx=5)

        self.current_text = self.ingredients_combo_box.get().capitalize()
        self.last_text_is_current_ingredient = (
            self.current_ingredient in Ingredient.ingredients_dict
        )
        self.update_combo_box_ingredients()
        self.ingredients_combo_box.set("Ingredient Name")
        self.done_button = Button(
            self,
            text="Done",
            command=lambda: (
                Program.Program.controller.change_frames(Recipes_frame.Recipes_frame),
                Program.Program.controller.change_frames(Side_frame.Side_frame, False),
            ),
        )
        self.done_button.pack(side="bottom", pady=(0, 20))

    def ingredients_combo_box_clicked_event(self):
        self.ingredients_combo_box_clicked = True

    def update_combo_box_ingredients(self):
        search_string = self.ingredients_combo_box.get().upper()
        if (
            not self.ingredients_combo_box_clicked
            and search_string == "INGREDIENT NAME"
        ):
            search_string = ""
        found_ingredients_dict = {}
        for ingredient_name in Ingredient.ingredients_dict:
            indx = ingredient_name.upper().find(search_string)
            if indx != -1:
                found_ingredients_dict.setdefault(indx, list())
                found_ingredients_dict[indx].append(ingredient_name)
        self.ingredients_based_on_search_list = []
        for key in sorted(tuple(found_ingredients_dict.keys())):
            self.ingredients_based_on_search_list += sorted(found_ingredients_dict[key])
        self.ingredients_combo_box["values"] = self.ingredients_based_on_search_list
        search_string = search_string.capitalize()
        self.current_text = search_string
        if search_string in Ingredient.ingredients_dict:
            self.current_ingredient()
        else:
            self.new_ingredient()

    def current_ingredient(self):
        self.last_text_is_current_ingredient = True
        self.add_button.grid_remove()
        self.remove_ingredient_button.grid()
        self.edit_button.grid()
        self.cost_label["text"] = f"Cost of {self.current_text}: $"
        ingredient = Program.Program.search_ingredient_name(self.current_text)
        self.cost_box.delete(0, END)
        self.cost_box.insert(0, str(ingredient.cost))
        self.unit_combo_box["state"] = "disabled"
        self.unit_combo_box.set(ingredient.unit)

    def new_ingredient(self):
        if self.last_text_is_current_ingredient:
            self.cost_box.delete(0, END)
            self.last_text_is_current_ingredient = False
        self.add_button.grid()
        self.remove_ingredient_button.grid_remove()
        self.edit_button.grid_remove()
        self.cost_label["text"] = f"Cost of {self.current_text}: $"
        self.unit_combo_box["state"] = "readonly"

    def edit_clicked(self):
        ingredient = Program.Program.search_ingredient_name(self.current_text)
        ingredient.cost = Program.Program.convert_string_to_float(self.cost_box.get())
        ingredient.update_recipes_cost()
        self.edit_button.config(bg="green")
        self.edit_button.after(
            1000, lambda: self.edit_button.config(bg="SystemButtonFace")
        )
        Program.Program.save(
            recipe_save_file="recipes.csv", ingredients_save_file="ingredients.csv"
        )

    def add_clicked(self):
        Program.Program.add_ingredient(
            self.current_text,
            Program.Program.convert_string_to_float(self.cost_box.get()),
            self.unit_combo_box.get(),
        )
        Program.Program.save(ingredients_save_file="ingredients.csv")
        Program.Program.update_due_to_item_added()
        self.current_ingredient()
        self.update_combo_box_ingredients()
        self.add_button.config(bg="green")
        self.add_button.after(
            1000, lambda: self.add_button.config(bg="SystemButtonFace")
        )

    def remove_clicked(self, parent):
        Program.Program.controller.bell()
        confirmation_frame = Frame(parent, bg=self.bg_color)
        confirmation_frame.grid(row=0, column=0, sticky="nsew")
        warning_text_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb("#CF6679"),
                Program.Program.convert_hex_to_rgb("#000000"),
                0.87,
            ),
        )
        warning_label = Label(
            confirmation_frame,
            text=f"WARNING:\nAre you sure you want to delete {self.current_text}?\nThis will delete the ingredient and remove it from all recipes.",
            bg="#CF6679",
            fg=warning_text_color,
        )
        warning_label.pack(fill="x")
        lower_frame = Frame(confirmation_frame, bg=self.bg_color)
        lower_frame.pack()
        no_button = Button(
            lower_frame,
            text="No",
            padx=30,
            command=lambda: (confirmation_frame.destroy()),
        )
        no_button.grid(row=0, column=0, padx=5)
        yes_button = Button(
            lower_frame,
            text="Yes",
            bg="red",
            fg="white",
            command=lambda: (
                self.delete_ingredient_process(),
                confirmation_frame.destroy(),
            ),
        )
        yes_button.grid(row=0, column=1, padx=5)

        if "#" in self.bg_color:
            lower_frame.update()
            self.no_button_image = Program.Program.create_rounded_button_image(
                self.bg_color,
                self.primary_color,
                self.primary_color_text,
                "No",
                no_button.winfo_width(),
                no_button.winfo_height(),
                22,
            )
            no_button.config(
                border="0",
                relief="flat",
                borderwidth=0,
                highlightthickness=0,
                activebackground=self.bg_color,
                image=self.no_button_image,
            )
            self.yes_button_image = Program.Program.create_rounded_button_image(
                self.bg_color,
                "#CF6679",
                warning_text_color,
                "Yes",
                yes_button.winfo_width(),
                yes_button.winfo_height(),
                22,
            )
            yes_button.config(
                border="0",
                relief="flat",
                borderwidth=0,
                highlightthickness=0,
                activebackground=self.bg_color,
                image=self.yes_button_image,
            )

    def delete_ingredient_process(self):
        Program.Program.delete_ingredient(self.current_text)
        Program.Program.save(
            recipe_save_file="recipes.csv", ingredients_save_file="ingredients.csv"
        )
        Program.Program.update_due_to_item_added()
        self.update_combo_box_ingredients()
        Program.Program.controller.frames[Edit_and_add_recipes.Edit_and_add_recipes].update_window()

    def change_colors(self, bg_color, primary_color, primary_variant, secondary_color):
        elevation_1_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(bg_color), (255, 255, 255), 0.05
            )
        )
        if Program.Program.light_mode:
            button_text_color = "#FFFFFF"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (0, 0, 0), 0.87
                )
            )
        else:
            button_text_color = "#000000"
            label_color = Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(elevation_1_color), (255, 255, 255), 0.87
                )
            )
        self.primary_color = primary_color
        self.primary_color_text = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(primary_color),
                Program.Program.convert_hex_to_rgb(button_text_color),
                0.87,
            )
        )
        self.bg_color = bg_color
        self.config(bg=bg_color)
        self.ingredients_combo_box.configure(
            style="colored.TCombobox",
        )
        self.ingredients_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {label_color} -background {elevation_1_color}"
            % self.ingredients_combo_box
        )
        self.cost_frame.config(bg=elevation_1_color)
        self.cost_label.config(bg=elevation_1_color, fg=label_color)
        box_color = Program.Program.convert_rgb_to_hex(
            Program.Program.overlay_colors(
                Program.Program.convert_hex_to_rgb(bg_color), (255, 255, 255), 0.11
            )
        )
        self.cost_box.config(
            bg=box_color,
            fg=label_color,
            insertbackground=label_color,
        )

        self.unit_frame.config(bg=elevation_1_color)
        self.unit_label.config(bg=elevation_1_color, fg=label_color)
        self.unit_combo_box.configure(
            style="colored.TCombobox",
        )
        self.unit_combo_box.tk.eval(
            f"[ttk::combobox::PopdownWindow %s].f.l configure -foreground {label_color} -background {elevation_1_color}"
            % self.unit_combo_box
        )

        self.button_frame.config(bg=bg_color)
        self.add_button.grid()
        self.remove_ingredient_button.grid()
        self.edit_button.grid()
        self.update()

        self.add_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Add Ingredient",
            self.add_button.winfo_width(),
            self.add_button.winfo_height(),
            22,
        )
        self.add_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.add_button_image,
        )

        self.remove_ingredient_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Remove Ingredient",
            self.remove_ingredient_button.winfo_width(),
            self.remove_ingredient_button.winfo_height(),
            22,
        )
        self.remove_ingredient_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.remove_ingredient_button_image,
        )

        self.edit_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Edit Ingredient",
            self.edit_button.winfo_width(),
            self.edit_button.winfo_height(),
            22,
        )
        self.edit_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.edit_button_image,
        )
        # self.ingredients_combo_box.set("")
        self.update_combo_box_ingredients()
        # self.ingredients_combo_box.set("Ingredient Name")

        self.done_button_image = Program.Program.create_rounded_button_image(
            bg_color,
            primary_color,
            Program.Program.convert_rgb_to_hex(
                Program.Program.overlay_colors(
                    Program.Program.convert_hex_to_rgb(primary_color),
                    Program.Program.convert_hex_to_rgb(button_text_color),
                    0.87,
                )
            ),
            "Done",
            self.done_button.winfo_width(),
            self.done_button.winfo_height(),
            22,
        )
        self.done_button.config(
            border="0",
            relief="flat",
            borderwidth=0,
            highlightthickness=0,
            activebackground=bg_color,
            image=self.done_button_image,
        )